package laf.behaviours;

import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import laf.time.Timer;

public abstract class TimerBehaviour  extends SimpleBehaviour {
	
	private long wakeupTime, period;
	private boolean finished;
	private int tickCount = 0;
	private Timer timer;

	public TimerBehaviour(Agent agent, long period) {
		super(agent);
		if (period <= 0) {
			throw new IllegalArgumentException("Period must be greater than 0");
		}
		this.period = period;
		timer = Timer.getInstance();
	}
	
	public void onStart() {
		if (!Timer.getInstance().isStarted()) {
			throw new RuntimeException("Timer must be started before TimerBehaviour can be started");
		}
		wakeupTime = timer.wakeupTime(period);
	}
	
	public final void action() {
		// Someone else may have stopped us in the meanwhile
		if (!finished) {
			long blockTime = wakeupTime - System.currentTimeMillis();
			if (blockTime <= 0) {
				// Timeout is expired --> execute the user defined action and
				// re-initialize wakeupTime
				tickCount++;
				onTick();
				wakeupTime = timer.wakeupTime(period);
				blockTime = wakeupTime - System.currentTimeMillis();
			}
			// Maybe this behaviour has been removed within the onTick() method
			if (myAgent != null && !finished) {
				block(blockTime);
			}
		}
	} 
	
	protected abstract void onTick();
	
	public final boolean done() {
		return finished;
	}
	
	/**
	 * Make this <code>TickerBehaviour</code> terminate.
	 * Calling stop() has the same effect as removing this TickerBehaviour, but is Thread safe
	 */
	public void stop() {
		finished = true;
	}
	
	/**
	 * Retrieve how many ticks were done (i.e. how many times this
	 * behaviour was executed) since the last reset.
	 * @return The number of ticks since the last reset
	 */
	public final int getTickCount() {
		return tickCount;
	}
}
